import socket,threading,os
from chat_room.chat_gui_v3_with_mysql.tools import mysql
class chat_server():
    def __init__(self,host,port,outtime=100,listen=5):
        self.server=socket.socket(socket.AF_INET,socket.SOCK_STREAM)#创建服务器socket
        self.server.bind((host,port))#绑定端口
        self.server.listen(listen)#设置监听
        self.usernames=[]#初始化在线用户列表
        self.clients=[]#初始化在线客户端
    def run(self):#开始运行
        while True:
            client,addr=self.server.accept()#等待客户端连接
            msg=client.recv(1024)
            msg=msg.decode()
            case=msg.split(":")[0]#解析第一条消息
            if case=='1':#case1为注册，标示为第一条消息的第一个字符
                self.client_signup(client,msg)#调用服务器注册方法
            elif case=='2':#case2为登录，标示为第一条消息的第一个字符
                self.client_login(client,msg)#调用服务器登录方法
            else:
                client.send("first message error,disconnect!".encode('utf-8'))#返回错误信息，第一条信息格式错误
                client.close()#关闭客户端连接
    def client_signup(self,client,msg):#客户端注册账户
        if ":" in msg and msg.count(":")==3:#判断是否为正确的注册信息
            id,signup_nick,signup_username,signup_password=msg.split(":")#解析登录数据
            user_info,sta=mysql("select * from users where username='%s'"%(signup_username))#将username调入数据库查询
            if sta==0:#数据库返回为0则为没有查到该username
                cur,sta1=mysql("insert into users (username,password,nick) values ('%s','%s','%s')"%(signup_username,signup_password,signup_nick))#将用户数据写入数据库
                if sta1!=0:#数据库返回不为0则为插入新注册用户数据成功
                    client.send('signup success'.encode('utf-8'))#返回客户端注册成功信息
                    client.close()#关闭客户端连接
                else:
                    client.send('signup failed'.encode('utf-8'))#返回客户端注册失败信息
                    client.close()#关闭客户端连接
            else:
                client.send("error username,disconnect!".encode('utf-8'))#返回给客户端username重复错误信息
                client.close()#关闭客户端连接
    def client_login(self,client,msg):#客户端登陆帐户
        if ":" in msg and msg.count(":")==2:#判断是否为正确的登录信息
            id,username_login,password_login=msg.split(":")#解析登录数据
            user_info,sta=mysql("select * from users where username='%s'"%(username_login))#将username调入数据库查询
            if sta!=0:#数据库返回值不为零则查询到该数据
                user_info=self.get_mysql_data(user_info,sta)#从mysql中读取用户信息
                id,username,password,nick=user_info#解析mysql用户信息
                if username in self.usernames:#判断客户端输入账户是否存在在线用户中
                    client.send("alread login,disconnect!".encode('utf-8'))
                    client.close()#关闭客户端连接
                else:
                    if password_login==password:#验证用户输入密码是否与数据库一致
                        client.send("login success".encode('utf-8'))#返回给客户端成功登录信息
                        self.clients.append(client)#将客户端加入客户端组
                        self.usernames.append(username)#加入在线用户组
                        threading.Thread(target=self.__send_msg,args=(client,id,nick,username)).start()#开启该客户端收发线程
                    else:
                        client.send("error password,disconnect!".encode('utf-8'))#返回给客户端密码错误信息
                        client.close()#关闭客户端连接
            else:
                client.send("error username,disconnect!".encode('utf-8'))#返回给客户端账号错误信息
                client.close()#关闭客户端连接
        else:
            client.send("error login msg type,disconnect!".encode('utf-8'))#返回给客户端登陆信息错误
            client.close()#关闭客户端连接
    def get_users_info(self):#从mysql中查询用户信息组
        data,sta=mysql('select * from users')#查询数据库users表中的信息，备注：数据库中users信息格式为id,username,password,nick
        data=self.get_mysql_data(data,sta)#调用获取mysql数据方法
        return data
    def get_mysql_data(self,data,sta):#读取mysql数据，单条信息为元组，多条信息转化为列表嵌套元组
        if sta==1:#如果mysql信息只有一条的读取方式，返回值为元组
            for i in data:
                return i
        else:#mysql的信息有多条的读取方式，返回值为列表
            data_list=[]
            for i in data:
                data_list.append(i)
            return data_list
    def __send_msg(self,client,id,nick,username):#接收用户消息然后广播
        while True:
            try:
                msg=client.recv(1024)
            except:#判断客户端是否断开连接
                self.clients.remove(client)#客户端断开则移除客户端组
                self.usernames.remove(username)#客户端断开则移除在线客户组
                client.close()#关闭客户端连接
                break
            mysql("insert into records (message,uid) values ('%s','%s')"%(msg.decode(),id))#将信息插入聊天框
            for c in self.clients:#广播消息
                if c==client:
                    pass
                else:
                    c.send((nick+":").encode('utf-8')+msg)
def main():
    host='192.168.0.78'
    port=9999
    cs=chat_server(host,port)
    cs.run()
if __name__=='__main__':
    main()


